home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / interapplication comm / menuscripter / sources / mswindow.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  25.1 KB  |  1,084 lines

  1. // MSWindow.c
  2. //
  3. // Original version by Jon Lansdell and Nigel Humphreys.
  4. // 4.0 and 3.1 updates by Greg Sutton.
  5. // ©Apple Computer Inc 1996, all rights reserved.
  6.  
  7. /*
  8.     Changes for 3.1 :
  9.     
  10.     12-Oct-95 : CW : Cleaned up DoContent and added call to DoWindowContentDrag
  11.                      Clean up CloseMyWindow and added call to RemoveDragHandlers
  12.                      Added InstallDragHandlers call to NewDocument
  13.                      Use HiliteControl on suspend/resume instead of Show/HideControl
  14.     1-Nov-95  : DS : Made Changes for GX Printing.
  15.  
  16.     Changes for 4.0 :
  17.  
  18.     17-Apr-96 : GS : Changed pascal calling conventions to C where possible.
  19. */
  20.  
  21. #include <Scrap.h>
  22. #include <Packages.h>
  23. #ifdef THINK_C
  24.     #include "PLStrs.h"
  25. #else
  26.     #include <PLStringFuncs.h>
  27. #endif
  28. #include <GXPrinting.h>
  29. #include <PrintingMessages.h>
  30.  
  31. #include "MSWindow.h"
  32. #include "MSMain.h"
  33. #include "MSDrag.h"
  34. #include "MSAERecording.h"
  35. #include "MSGXPrinting.h"
  36. #include "MSResultWind.h"
  37. #include "MSAEWindowUtils.h"
  38.  
  39. #define    kControlInvisible        0
  40. #define    kControlVisible            0xFF             
  41. #define    kScrollbarWidth            16
  42. #define    kScrollbarAdjust        (kScrollbarWidth - 1)
  43. #define    kScrollTweek            2
  44. #define    kTextOffset                5 
  45. #define    kButtonScroll            10
  46.             
  47. #define    kHOffset                20   // Stagger window offsets
  48. #define    kVOffset                20
  49.             
  50. #define    kTBarHeight                20
  51. #define    kMBarHeight                20
  52.  
  53. #pragma segment Window
  54.  
  55. DPtr    DPtrFromWindowPtr(WindowPtr theWindow)
  56. {
  57.     if ( theWindow && IsDocumentWindow( theWindow ) )
  58.         return((DPtr)GetWRefCon(theWindow));
  59.     else
  60.         return(NULL);
  61. } // DPtrFromWindowPtr
  62.  
  63.     
  64. #pragma segment main
  65.  
  66.  
  67. //  Scroll the TERec around to match up to the potentially updated scrollbar
  68. //  values. This is really useful when the window resizes such that the
  69. //  scrollbars become inactive and the TERec had been previously scrolled.
  70.  
  71. void    AdjustTE( DPtr theDoc )
  72. {
  73.     short    h;
  74.     short    v;
  75.     TEHandle myText;
  76.     
  77.     myText = theDoc->theText;
  78.     h = ((*myText)->viewRect.left - (*myText)->destRect.left) -
  79.     GetCtlValue(theDoc->hScrollBar) + kTextOffset;
  80.              
  81.     v = ((*myText)->viewRect.top - (*myText)->destRect.top) - 
  82.     GetCtlValue(theDoc->vScrollBar) + kTextOffset;
  83.                      
  84.     if (h || v)
  85.     {
  86.         TEScroll(h, v, theDoc->theText);
  87.         DrawPageExtras(theDoc);
  88.     }
  89. } // AdjustTE
  90.     
  91.     
  92. // Calculate the new control maximum value and current value, whether it is the horizontal or
  93. // vertical scrollbar. The vertical max is calculated by comparing the number of lines to the
  94. // vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document
  95. // width to the width of the viewRect. The current values are set by comparing the offset between
  96. // the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by
  97. // calling ShowControl.
  98.  
  99. // TEStyleSample-vertical max originally used line by line calculations-lineheight was a
  100. // constant value so it was easy to figure out what the range should be and pin the value
  101. // within range. Now we need to use max and min values in pixels rather than in nlines.
  102.  
  103. #pragma segment main
  104.  
  105. void    AdjustHV( Boolean isVert, ControlHandle control, DPtr theDoc, Boolean canRedraw )
  106. {
  107.     TEHandle    docTE;
  108.     short       value;
  109.     short        max;
  110.     short        oldValue;
  111.     short        oldMax;
  112.     Rect        sizeRect;
  113.     
  114.     GetRectOfPage( theDoc, &sizeRect );
  115.     docTE    = theDoc->theText;
  116.     
  117.     oldValue = GetCtlValue(control);
  118.     oldMax   = GetCtlMax(control);
  119.     if (isVert)
  120.     {
  121.         // new for TEStyleSample
  122.         max = TEGetHeight((*docTE)->nLines, 0, docTE) -
  123.                    ((*docTE)->viewRect.bottom - (*docTE)->viewRect.top);
  124.     
  125.     }
  126.     else
  127.         max = sizeRect.right - ((*docTE)->viewRect.right - (*docTE)->viewRect.left);
  128.             
  129.     max += kTextOffset + kTextOffset; // Allow over scroll by kTextOffset
  130.             
  131.     if (max < 0)
  132.     max = 0; // check for negative values
  133.         
  134.     SetCtlMax(control, max);
  135.     
  136.     if (isVert)
  137.         value = (*docTE)->viewRect.top - (*docTE)->destRect.top;
  138.     else
  139.         value = (*docTE)->viewRect.left - (*docTE)->destRect.left;
  140.                 
  141.     value += kTextOffset;
  142.             
  143.     if (value < 0)
  144.         value = 0;
  145.     else
  146.         if (value > max)
  147.             value = max; // pin the value to within range
  148.                     
  149.     SetCtlValue(control, value);
  150.     if (canRedraw && ((max != oldMax) || (value != oldValue)))
  151.         ShowControl(control); // check to see if the control can be re-drawn
  152. } // AdjustHV
  153.  
  154.  
  155. #pragma segment Main
  156.  
  157. // Simply call the common adjust routine for the vertical and horizontal scrollbars.
  158.  
  159. void    AdjustScrollValues( DPtr theDoc, Boolean canRedraw )
  160. {        
  161.     AdjustHV(true,  theDoc->vScrollBar, theDoc, canRedraw);
  162.     AdjustHV(false, theDoc->hScrollBar, theDoc, canRedraw);
  163. } // AdjustScrollValues
  164.  
  165.  
  166. // Return a rectangle that is inset from the portRect by the size of
  167. //  the scrollbars and a little extra margin.
  168.  
  169. void    GetTERect( WindowPtr window, Rect *teRect )
  170. {
  171.     *teRect = window->portRect;
  172.     (*teRect).bottom -= kScrollbarAdjust; // and for the scrollbars
  173.     (*teRect).right  -= kScrollbarAdjust;
  174. } // GetTERect
  175.  
  176.  
  177. // Re-calculate the position and size of the viewRect and the scrollbars.
  178. //  kScrollTweek compensates for off-by-one requirements of the scrollbars
  179. //  to have borders coincide with the growbox.
  180.  
  181. void    AdjustScrollSizes( DPtr theDoc )
  182. {  
  183.     Rect    teRect;
  184.     Rect    myPortRect;
  185.     
  186.     GetTERect(theDoc->theWindow, &teRect); // start with teRect
  187.     myPortRect = theDoc->theWindow->portRect;
  188.     
  189.     (*(theDoc->theText))->viewRect = teRect;
  190.     
  191.     MoveControl(theDoc->vScrollBar, myPortRect.right - kScrollbarAdjust, - 1);
  192.     SizeControl(theDoc->vScrollBar, 
  193.                  kScrollbarWidth, 
  194.                      (myPortRect.bottom - myPortRect.top) - (kScrollbarAdjust - kScrollTweek));
  195.         
  196.     MoveControl(theDoc->hScrollBar, - 1, myPortRect.bottom - kScrollbarAdjust);
  197.     SizeControl(theDoc->hScrollBar,
  198.                     (myPortRect.right - myPortRect.left) - (kScrollbarAdjust - kScrollTweek),
  199.                         kScrollbarWidth);
  200. } // AdjustScrollSizes
  201.  
  202. #pragma segment Window
  203.  
  204. // Turn off the controls by jamming a zero into their contrlVis fields
  205. //  (HideControl erases them and we don't want that). If the controls are to
  206. //  be resized as well, call the procedure to do that, then call the procedure
  207. //  to adjust the maximum and current values. Finally reset the controls
  208. //  to be visible if not in background.
  209.  
  210. void    AdjustScrollbars( DPtr theDoc, Boolean  needsResize )
  211. {
  212.     (*(theDoc->vScrollBar))->contrlVis = kControlInvisible; // turn them off
  213.     (*(theDoc->hScrollBar))->contrlVis = kControlInvisible;
  214.     
  215.     if (needsResize) // move and size if needed
  216.     AdjustScrollSizes(theDoc);
  217.     
  218.     AdjustScrollValues(theDoc, !needsResize); // fool with max and current value
  219.     
  220.     // Now, restore visibility in case we never had to ShowControl during adjustment
  221.     
  222.     if (!gInBackground)
  223.     {
  224.         (*(theDoc->vScrollBar))->contrlVis = kControlVisible; // turn them on
  225.         (*(theDoc->hScrollBar))->contrlVis = kControlVisible;
  226.     }
  227.     else
  228.     {         // make sure they stay invisible
  229.         if ((*(theDoc->vScrollBar))->contrlVis)
  230.             HideControl(theDoc->vScrollBar);
  231.         if ((*(theDoc->vScrollBar))->contrlVis)
  232.             HideControl(theDoc->hScrollBar);
  233.     }
  234. } // AdjustScrollbars
  235.  
  236.  
  237. #pragma segment Window
  238.  
  239. void    GetWinContentRect( WindowPtr theWindow, Rect *r )
  240. {
  241.     *r         = theWindow->portRect;
  242.     r->right  -= kScrollbarAdjust;
  243.     r->bottom -= kScrollbarAdjust;
  244. } // GetWinContentRect
  245.  
  246.     
  247. #pragma segment Window
  248.         
  249. void    InvalidateDocument( DPtr theDoc )
  250. {
  251.     GrafPtr oldPort;
  252.         
  253.     GetPort(&oldPort);
  254.     SetPort(theDoc->theWindow);
  255.     InvalRect(&theDoc->theWindow->portRect);
  256.     SetPort(oldPort);
  257.                         
  258.  
  259. // Called when the window has been resized to fix up the controls and content.
  260.  
  261. void    ResizeWindow( DPtr theDoc )
  262. {
  263.     AdjustScrollbars(theDoc, true);
  264.     AdjustTE(theDoc);
  265.     InvalidateDocument(theDoc);
  266. } // ResizeWindow
  267.  
  268.  
  269. // Called when the window has been resized to fix up the controls and content
  270.  
  271. void    ResizePageSetupForDocument( DPtr theDoc )
  272. {
  273.     Rect pageRect;
  274.     
  275.     GetRectOfPage( theDoc, &pageRect );
  276.     (*(theDoc->theText))->destRect.right = (*(theDoc->theText))->destRect.left + pageRect.right;
  277.     TECalText(theDoc->theText);
  278.     
  279.     ResizeWindow(theDoc);
  280. } // ResizePageSetupForDocument
  281.  
  282.  
  283. #pragma segment Main
  284.  
  285. // Common algorithm for setting the new value of a control. It returns the actual amount
  286. //  the value of the control changed. Note the pinning is done for the sake of returning
  287. //  the amount the control value changed.
  288.  
  289. void    CommonAction( ControlHandle control, short *amount )
  290. {
  291.     short   value;
  292.     short   max;
  293.     
  294.     value   = GetCtlValue(control); // get current value
  295.     max     = GetCtlMax(control);    // and max value
  296.     *amount = value - *amount;
  297.     if (*amount < 0)
  298.         *amount = 0;
  299.     else if (*amount > max)
  300.         *amount = max;
  301.     
  302.     SetCtlValue(control, *amount);
  303.     *amount = value - *amount;        // calculate true change
  304. } // CommonAction
  305.  
  306.  
  307. #pragma segment Main
  308.  
  309. // Determines how much to change the value of the vertical scrollbar by and how
  310. //  much to scroll the TE record.
  311.  
  312. pascal void VActionProc( ControlHandle control, short part )
  313. {
  314.     short           amount;
  315.     WindowPtr       window;
  316.     DPtr            theDoc;
  317.     
  318.     if ( part )
  319.     {
  320.         window = (*control)->contrlOwner;
  321.         theDoc = DPtrFromWindowPtr(window);
  322.         switch (part)
  323.         {
  324.             case inUpButton:
  325.             case inDownButton:
  326.                 amount = 24;
  327.                 break;
  328.                 
  329.             case inPageUp:
  330.             case inPageDown:
  331.                 amount = (*(theDoc->theText))->viewRect.bottom - 
  332.                                  (*(theDoc->theText))->viewRect.top;
  333.                 break;
  334.         } // case
  335.         
  336.         if (part == inDownButton || part == inPageDown)
  337.         amount = -amount; // reverse direction
  338.         
  339.         CommonAction(control, &amount);
  340.         
  341.         if (amount)
  342.         {
  343.             TEScroll(0, amount, theDoc->theText);
  344.             DrawPageExtras(theDoc);
  345.         }
  346.     } // if
  347. } // VActionProc
  348.  
  349.  
  350. #pragma segment Main
  351.  
  352. // Determines how much to change the value of the horizontal scrollbar by and how
  353. //  much to scroll the TE record.
  354.  
  355. pascal void HActionProc(ControlHandle control, short part)
  356. {
  357.     short      amount;
  358.     WindowPtr  window;
  359.     DPtr       theDoc;
  360.     
  361.     if ( part )
  362.     {
  363.         window = (*control)->contrlOwner;
  364.         theDoc = DPtrFromWindowPtr(window);
  365.         switch ( part )
  366.         {
  367.             case inUpButton:
  368.             case inDownButton:
  369.                 amount = kButtonScroll; // a few pixels
  370.                 break;
  371.                 
  372.             case inPageUp:
  373.             case inPageDown:
  374.                 amount = (*(theDoc->theText))->viewRect.right - 
  375.                             (*(theDoc->theText))->viewRect.left; // a page
  376.                 break;
  377.         } // switch
  378.  
  379.         if (part == inDownButton || part == inPageDown)
  380.         amount = - amount; // reverse direction
  381.         
  382.         CommonAction(control, &amount);
  383.         if (amount)
  384.         {
  385.             TEScroll(amount, 0, theDoc->theText);
  386.             DrawPageExtras(theDoc);
  387.         }
  388.     } // if
  389. } // HActionProc
  390.  
  391.  
  392. //        Name:             ShowSelect
  393. //        Purpose:        Scrolls the text selection into view.
  394.  
  395. #pragma segment Window
  396.  
  397. void    ShowSelect( DPtr theDoc )
  398. {
  399.     AdjustScrollbars(theDoc, false);
  400.     
  401.         //    Let TextEdit do the hard work of keeping the selection visible…
  402.     
  403.     TEAutoView(true, theDoc->theText);
  404.     TESelView(theDoc->theText);
  405.     TEAutoView(false, theDoc->theText);
  406.     
  407.         //    Now rematch the text and the scrollbars…
  408.     
  409.     SetCtlValue(theDoc->hScrollBar,
  410.                     (*(theDoc->theText))->viewRect.left - 
  411.                         (*(theDoc->theText))->destRect.left + kTextOffset);
  412.     
  413.     SetCtlValue(theDoc->vScrollBar,
  414.                     (*(theDoc->theText))->viewRect.top - 
  415.                         (*(theDoc->theText))->destRect.top  + kTextOffset);
  416. } // ShowSelect
  417.  
  418.  
  419. #pragma segment Window
  420.  
  421. void    OffsetWindow( WindowPtr aWindow )
  422. {
  423.     short    theWidth;
  424.     short    theHeight;
  425.     short    theHScreen;
  426.     short    theVScreen;
  427.     short    xWidth;
  428.     short    xHeight;
  429.     short    hMax;
  430.     short    vMax;
  431.     short    wLeft;
  432.     short    wTop;
  433.     long    docCount;
  434.      
  435.     theWidth  = aWindow->portRect.right - aWindow->portRect.left;
  436.     theHeight = aWindow->portRect.bottom - aWindow->portRect.top + kTBarHeight;
  437.     
  438.     theHScreen = qd.screenBits.bounds.right  - qd.screenBits.bounds.left;
  439.     theVScreen = qd.screenBits.bounds.bottom - qd.screenBits.bounds.top;
  440.     
  441.     xWidth  = theHScreen - theWidth;
  442.     xHeight = theVScreen - (theHeight + kMBarHeight);
  443.     
  444.     hMax = (xWidth / kVOffset) + 1;
  445.     vMax = (xHeight / kVOffset) + 1;
  446.     
  447.     docCount = CountDocuments( );
  448.     if ( ! IsVisible( aWindow ) )
  449.         docCount++;        // Offset has been called on a window still hidden
  450.     
  451.     wLeft = ( docCount % hMax ) * kVOffset;
  452.     wTop  = ( ( docCount % vMax ) * kVOffset ) + kTBarHeight + kMBarHeight;
  453.     
  454.     MoveWindow(aWindow, wLeft, wTop, false);
  455. }
  456.  
  457. /*
  458. // Returns the update region in local coordinates.
  459.  
  460. void    GetLocalUpdateRgn( WindowPtr window, RgnHandle localRgn )
  461. {
  462.     CopyRgn(((WindowPeek)window)->updateRgn, localRgn); // save old update region
  463.     OffsetRgn(localRgn,
  464.                 window->portBits.bounds.left, 
  465.                     window->portBits.bounds.top); // convert to local coords
  466. } // GetLocalUpdateRgn
  467. */
  468.  
  469. #pragma segment Window
  470.  
  471. void    MyGrowWindow( WindowPtr w, Point p )
  472. {
  473.     GrafPtr savePort;
  474.     long    theResult;
  475.     Rect    r;
  476.     
  477.     GetPort(&savePort);
  478.     SetPort(w);
  479.     SetRect(&r, 80, 80, qd.screenBits.bounds.right, qd.screenBits.bounds.bottom);
  480.     theResult = GrowWindow(w, p, &r);
  481.     if (theResult)
  482.         IssueSizeWindow(w, LoWord(theResult), HiWord(theResult));
  483.     
  484.     SetPort(savePort);
  485. }
  486.  
  487.  
  488. #pragma segment Window
  489.  
  490. // Because windows can be hidden we must check for menu changes
  491.  
  492. void ShowMSWindow( WindowPtr theWindow )
  493. {
  494.     ShowWindow( theWindow );
  495.     if ( FrontWindow( ) == theWindow )
  496.     {
  497.         DoActivate( GetNthWindow( 2 ), false );
  498.         DoActivate( theWindow, true );
  499.     }
  500.     CheckMenus( );
  501. }
  502.  
  503. void HideMSWindow( WindowPtr theWindow )
  504. {
  505.     Boolean        fActivate;
  506.  
  507.     fActivate = ( FrontWindow( ) == theWindow );
  508.     HideWindow( theWindow );
  509.     if ( fActivate )
  510.     {
  511.         DoActivate( theWindow, false );
  512.         DoActivate( GetNthWindow( 1 ), true );
  513.     }
  514.     
  515.     CheckMenus( );
  516. }
  517.  
  518. #pragma segment Window
  519.  
  520. void    DoZoom( WindowPtr w, short c, Point p )
  521. {
  522.     GrafPtr savePort;
  523.     
  524.     GetPort(&savePort);
  525.     SetPort(w);
  526.     if (TrackBox(w, p, c))
  527.     {
  528.         EraseRect(&w->portRect);
  529.         IssueZoomCommand(w, c);
  530.     }
  531. }
  532.  
  533. #pragma segment Window
  534.  
  535. void    DoContent( WindowPtr theWindow, EventRecord theEvent )
  536. {
  537.     short            cntlCode;
  538.     short            part;
  539.     short            value;
  540.     ControlHandle    theControl;
  541.     GrafPtr            savePort;
  542.     Boolean            extend;
  543.     DPtr            theDoc;
  544.     Point            localPt;
  545.     
  546.     
  547.     GetPort ( &savePort );
  548.     SetPort ( theWindow );
  549.     theDoc = DPtrFromWindowPtr ( theWindow );
  550.     
  551.     localPt = theEvent.where;
  552.     GlobalToLocal ( &localPt );
  553.     cntlCode = FindControl ( localPt, theWindow, &theControl );
  554.     if ( cntlCode == 0 )
  555.     {
  556.         if ( UserWantsToDrag ( theWindow, theEvent.where ) )
  557.         {
  558.             if ( DoWindowContentDrag ( theWindow, &theEvent ) )
  559.                 TEClick ( localPt, false, theDoc->theText );
  560.         }
  561.         else
  562.         {
  563.             // only extend the selection if the shiftkey is down
  564.             extend = (theEvent.modifiers & shiftKey);
  565.             if ( PtInDocument ( localPt, theDoc ) )
  566.                 TEClick ( localPt, extend, theDoc->theText );
  567.         }
  568.     }
  569.     else if ( cntlCode == inThumb )
  570.     {
  571.         value = GetCtlValue(theControl);
  572.         part  = TrackControl(theControl, localPt, nil);
  573.         if (part)
  574.         {
  575.             value -= GetCtlValue(theControl);
  576.             if (value)
  577.             {
  578.                 if (theControl == theDoc->vScrollBar)
  579.                     TEScroll(0, value, theDoc->theText);
  580.                 else
  581.                     TEScroll(value, 0, theDoc->theText);
  582.                 DrawPageExtras(theDoc);
  583.             }
  584.         }
  585.     }
  586.     else
  587.     {
  588.         if (theControl == theDoc->vScrollBar)
  589.             part = TrackControl(theControl, localPt, (ControlActionUPP) gVScrollActionUPP);
  590.         else
  591.             part = TrackControl(theControl, localPt, (ControlActionUPP) gHScrollActionUPP);
  592.     }
  593.  
  594.     SetPort(savePort);
  595. }
  596.  
  597.  
  598.  
  599. void    DoBackgroundContent( WindowPtr theWindow, EventRecord theEvent)
  600. {
  601.     Point            thePoint;
  602.     GrafPtr            savePort;
  603.     RgnHandle        dragRgn;
  604.     DPtr              theDoc;
  605.  
  606.     GetPort ( &savePort );
  607.     SetPort ( theWindow );
  608.     theDoc = DPtrFromWindowPtr ( theWindow );
  609.     thePoint = theEvent.where;
  610.     GlobalToLocal ( &thePoint );
  611.     
  612.     
  613.     dragRgn = NewRgn ( );
  614.     GetSelectedTextRgn ( theDoc, dragRgn );
  615.     if ( PtInRgn ( thePoint, dragRgn ) )
  616.     {
  617.         if ( DoWindowContentDrag ( theWindow, &theEvent ) )
  618.             SelectWindow (theWindow );
  619.     }
  620.     else
  621.         SelectWindow ( theWindow );
  622.     
  623.     SetPort ( savePort );
  624.  
  625.     return;
  626. }
  627.  
  628. #pragma segment Window
  629.  
  630.  
  631. OSErr    DoActivate( WindowPtr theWindow, Boolean activate )
  632. {
  633.     Rect  r;
  634.     DPtr  theDoc;
  635.     OSErr err = noErr;
  636.         
  637.     if (theWindow)
  638.         if (Ours(theWindow))
  639.         {
  640.             theDoc = DPtrFromWindowPtr(theWindow);
  641.             SetPort(theWindow);
  642.             DrawGrowIcon(theWindow);
  643.             GetWinContentRect(theWindow, &r);
  644.             InvalRect(&r);
  645.             if ( activate )
  646.             {
  647.                 if ( theDoc->windowType == kOrdinaryWind )                        
  648.                     TEActivate(theDoc->theText);
  649.                 HiliteControl ( theDoc->vScrollBar, 0 );
  650.                 HiliteControl ( theDoc->hScrollBar, 0 );
  651.                 
  652.                 SetMenuItemState ( false, myMenus[editM], undoCommand );
  653.                 err = TEFromScrap();
  654.                 CheckMenus( );
  655.             }
  656.             else
  657.             {
  658.                 TEDeactivate( theDoc->theText );
  659.                 HiliteControl ( theDoc->vScrollBar, 255 );
  660.                 HiliteControl ( theDoc->hScrollBar, 255 );
  661.                 
  662.                 err = ZeroScrap();
  663.                 err = TEToScrap();
  664.             }
  665.         }
  666.  
  667.     return err;
  668. }
  669.  
  670. #pragma segment Window
  671.  
  672. void    GetPageEnds( short pageHeight, TEHandle theText,
  673.                                 PageEndsArray  pageBounds, short *nPages)
  674. {
  675.     short  pageBase;      // total pixel offset of pages so far
  676.     short  thisLine;
  677.     short  lastLine;
  678.     short  pageSoFar;
  679.     short  thisPage;      // Current page being calced
  680.     short  thisLineH;     // Height of text line
  681.     short  pageFirstLine; // Line # of top of page
  682.         
  683.     pageBase   = 0;
  684.     thisLine   = 1;
  685.     lastLine   = (*theText)->nLines;
  686.     
  687.     thisPage   = 0;
  688.     pageSoFar  = 0;
  689.     while ((thisLine <= lastLine) || (pageSoFar!=0))
  690.     {
  691.         pageFirstLine = thisLine;
  692.         thisLineH     = TEGetHeight(thisLine, thisLine, theText);
  693.         
  694.         while ((thisLineH+pageSoFar<pageHeight) && (thisLine <= lastLine))
  695.         {
  696.             pageSoFar += thisLineH;
  697.             thisLine++;
  698.             thisLineH = TEGetHeight(thisLine, thisLine, theText);
  699.         }
  700.             
  701.         if (pageSoFar)
  702.         {
  703.             pageBounds[thisPage] = pageSoFar+pageBase;
  704.             pageBase  = pageBounds[thisPage];
  705.             thisPage++;
  706.             pageSoFar = 0;
  707.         }
  708.             
  709.         //    Special case text line taller than page
  710.         
  711.         if ((thisLine  == pageFirstLine) &&
  712.              (thisLineH > pageHeight))
  713.             {
  714.                 do {
  715.                     pageBounds[thisPage] = pageBase+pageHeight;
  716.                     pageBase   = pageBounds[thisPage];
  717.                     thisPage  += 1;
  718.                     thisLineH -= pageHeight;
  719.                 } while (thisLineH >= pageHeight);
  720.                 pageSoFar = thisLineH;    // Carry bottom of large line to next page
  721.                 thisLine += 1;             // carry xs on as pageSoFar and start measuring next line
  722.             }
  723.     }
  724.         
  725.     *nPages = thisPage;
  726. } // GetPageEnds
  727.  
  728.  
  729. void    DrawPageBreaks( DPtr theDoc )
  730. {
  731.     PageEndsArray    pageEnds;
  732.     short           nPages;
  733.     short           ctr;
  734.     short           lineBase;
  735.     short           pageHeight;
  736.     Rect            viewRect;
  737.     Rect            pageRect;
  738.                 
  739.     GetRectOfPage( theDoc, &pageRect );
  740.     pageHeight = pageRect.bottom - pageRect.top;
  741.             
  742.     GetPageEnds(pageHeight, theDoc->theText, pageEnds, &nPages);
  743.                                         
  744.     lineBase = (*(theDoc->theText))->destRect.top;
  745.     viewRect = (*(theDoc->theText))->viewRect;
  746.     
  747.     PenPat(&qd.gray);
  748.     for (ctr = 0; ctr<nPages-1; ctr++)
  749.     {
  750.         MoveTo(viewRect.left, lineBase+pageEnds[ctr]);
  751.         LineTo(viewRect.right,lineBase+pageEnds[ctr]);
  752.     }
  753.  
  754.     PenNormal();
  755. } // DrawPageBreaks
  756.  
  757.         
  758. void    DrawPageExtras( DPtr theDoc )
  759. {
  760.     GrafPtr   oldPort;
  761.     RgnHandle    oldClip;
  762.     Rect          rectToClip;
  763.         
  764.     GetPort(&oldPort);
  765.     SetPort(theDoc->theWindow);
  766.             
  767.     oldClip = NewRgn();
  768.     GetClip(oldClip);
  769.             
  770.     GetWinContentRect(theDoc->theWindow,&rectToClip);
  771.     ClipRect(&rectToClip);
  772.                     
  773.         // and then the page breaks
  774.     DrawPageBreaks(theDoc);
  775.     
  776.     SetClip(oldClip);
  777.     
  778.     DisposeRgn(oldClip);
  779.     
  780.     SetPort(oldPort);
  781. } // DrawPageExtras
  782.  
  783.  
  784. void    DoUpdate( WindowPtr theWindow )
  785. {
  786.     GrafPtr        savePort;
  787.     Rect        rectClip;
  788.     DPtr        theDocument;
  789.     
  790.     
  791.     theDocument = DPtrFromWindowPtr ( theWindow );
  792.     if ( Ours ( theWindow ) )
  793.     {
  794.         GetPort ( &savePort );
  795.         SetPort ( theWindow );
  796.         BeginUpdate ( theWindow );
  797.         
  798.         ClipRect(&theWindow->portRect);
  799.         EraseRect(&theWindow->portRect);
  800.         DrawControls(theWindow);
  801.         DrawGrowIcon(theWindow);
  802.         
  803.         GetWinContentRect(theWindow, &rectClip);
  804.         ClipRect(&rectClip);
  805.         
  806.         TEUpdate(&theWindow->portRect, theDocument->theText);
  807.         
  808.         DrawPageExtras(theDocument);
  809.         
  810.         EndUpdate(theWindow);
  811.         ClipRect(&theWindow->portRect);
  812.         
  813.         SetPort ( savePort );
  814.     }
  815.     
  816.     return;
  817. } // DoUpdate
  818.  
  819.  
  820. #pragma segment Window
  821.  
  822. DPtr    NewDocument( Boolean isForOldDoc, WindowPtr behindWindow )
  823. {
  824.     Rect           destRect;
  825.     Rect           viewRect;
  826.     Rect           vScrollRect;
  827.     Rect           hScrollRect;
  828.     DPtr           myDoc;
  829.     WindowPtr      myWindow;
  830.     ControlHandle  vScroll;
  831.     ControlHandle  hScroll;
  832.     Str255         theName;
  833.     Str255         newNumber;
  834.     Rect           pageRect;
  835.  
  836.     myDoc = nil;
  837.     myWindow = GetNewWindow(WindowID, nil, behindWindow);
  838.     if (myWindow)
  839.     {
  840.         if (isForOldDoc==false)
  841.         {
  842.             GetWTitle(myWindow, theName);
  843.             NumToString(++gNewDocCount, newNumber);
  844.             if (gNewDocCount>1)
  845.             {
  846.                 PLstrcat(theName, (unsigned char *)"\p #");
  847.                 PLstrcat(theName, newNumber);
  848.                 SetWTitle(myWindow, theName);
  849.             }
  850.         }
  851.             
  852.         OffsetWindow(myWindow);
  853.  
  854.         SetPort(myWindow);
  855.  
  856.         myDoc = (DPtr)NewPtr(sizeof(DocRec));
  857.  
  858.         SetWRefCon(myWindow, (long)myDoc);
  859.  
  860.         myDoc->theWindow  = myWindow;
  861.         myDoc->windowType = kOrdinaryWind;
  862.  
  863.         vScrollRect = myWindow->portRect;
  864.  
  865.         vScrollRect.left  = vScrollRect.right - kScrollbarAdjust;
  866.         vScrollRect.right = vScrollRect.left  + kScrollbarWidth;
  867.  
  868.         vScrollRect.bottom = vScrollRect.bottom - 14;
  869.         vScrollRect.top    = vScrollRect.top - 1;
  870.         
  871.         vScroll = NewControl(myWindow, &vScrollRect, (unsigned char *)"\pScrollBar", true, 0, 0, 0, scrollBarProc, 0);
  872.  
  873.         hScrollRect = myWindow->portRect;
  874.         hScrollRect.top = hScrollRect.bottom - kScrollbarAdjust;
  875.         hScrollRect.bottom = hScrollRect.top + kScrollbarWidth;
  876.  
  877.         hScrollRect.right = hScrollRect.right - 14;
  878.         hScrollRect.left  = hScrollRect.left - 1;
  879.         hScroll = NewControl(myWindow, &hScrollRect, (unsigned char *)"\pScrollBar", true, 0, 0, 0, scrollBarProc, 0);
  880.  
  881.         myDoc->vScrollBar = vScroll;
  882.         myDoc->hScrollBar = hScroll;
  883.     
  884.         myDoc->dirty = false;
  885.  
  886.         GetTERect(myWindow, &viewRect);
  887.         destRect = viewRect;
  888.  
  889.         myDoc->theFont  = times;
  890.         myDoc->theStyle = 0;
  891.         myDoc->theSize  = 12;
  892.  
  893.         myDoc->documentJob   = nil;
  894.         myDoc->thePrintSetup = nil;
  895.         
  896.         if (gGXIsPresent)
  897.         {
  898.             if (GXNewJob(&(myDoc->documentJob)) == noErr)
  899.                 GXInstallApplicationOverride(myDoc->documentJob,
  900.                                              gxPrintingEventMsg,
  901.                                              NewGXPrintingEventProc(GXPrintingEventOverride));
  902.         }
  903.         else
  904.         {
  905.             myDoc->thePrintSetup = (THPrint)NewHandle(sizeof(TPrint));
  906.             
  907.             PrOpen();
  908.             PrintDefault(myDoc->thePrintSetup);
  909.             PrClose();
  910.         }
  911.     
  912.     
  913.         GetRectOfPage( myDoc, &pageRect );
  914.         destRect.right = destRect.left + pageRect.right;
  915.         
  916.         OffsetRect(&destRect, kTextOffset, kTextOffset);
  917.         
  918.         TextFont(times);
  919.         TextSize(12);
  920.         TextFace(0);
  921.  
  922.         myDoc->theText = TEStylNew(&destRect, &viewRect);
  923.  
  924. // SetClikLoop(@AutoScroll, myDoc->theText);
  925.  
  926.         myDoc->theFileName[0] = 0;
  927.         myDoc->everSaved      = false;
  928.         myDoc->theWindow      = myWindow;
  929.         ResizeWindow(myDoc);
  930.         
  931.         InstallDragHandlers ( myWindow );
  932.         
  933.         myDoc->theScriptID = kOSANullScript;
  934.     }
  935.  
  936.     return(myDoc);
  937. }
  938.  
  939.  
  940. #pragma segment Window
  941.  
  942. void    CloseMyWindow( WindowPtr aWindow )
  943. {
  944.     DPtr     aDocument;
  945.     TEHandle theText;
  946.  
  947.     if (IsThisResultWind(aWindow))
  948.         CloseResultWind(aWindow);
  949.     else
  950.     {
  951.         HideMSWindow(aWindow);
  952.         aDocument = DPtrFromWindowPtr(aWindow);
  953.         
  954.         theText = aDocument->theText;
  955.         TEDispose(theText);
  956.         
  957.         if (aDocument->thePrintSetup)
  958.             DisposHandle((Handle)aDocument->thePrintSetup);
  959.         
  960.         if (aDocument->documentJob)
  961.             GXDisposeJob(aDocument->documentJob);
  962.         
  963.         RemoveDragHandlers ( aWindow );
  964.         
  965.         DisposPtr((Ptr)aDocument);
  966.     
  967.         DisposeWindow(aWindow);
  968.     }
  969. }
  970.  
  971.             
  972. //        Name     :    PrintWindow
  973. //        Function :    Prints the document supplied in theDoc. askUser controls interaction
  974. //                       with the user.
  975. //                             
  976. //                    Uses extra memory equal to the size of the textedit use in the 
  977. //                     printed document.
  978.     
  979. void    PrintWindow( DPtr theDoc, Boolean askUser )
  980. {
  981.     GrafPtr            oldPort;
  982.     TEHandle        printerTE;
  983.     TPPrPort        printerPort;
  984.     Rect            printView;
  985.     PageEndsArray     pageBounds;
  986.     short            nPages;
  987.     short            pageCtr;
  988.     Boolean            abort;
  989.     Rect            rectToClip;
  990.     TPrStatus        thePrinterStatus;
  991.     DialogPtr        progressDialog;
  992.     WindowPtr       tempWind;                 // Temp window to create TERec in 
  993.     Rect            tempWindRect = {0,0,0,0}; // Bounds for temp window
  994.     abort = false;
  995.         
  996.  
  997.     //    Preserve the current port
  998.  
  999.     GetPort(&oldPort);
  1000.     PrOpen();
  1001.         
  1002.     if (askUser)
  1003.         abort = !PrJobDialog(theDoc->thePrintSetup);
  1004.             
  1005.     if (abort)
  1006.     {
  1007.         PrClose();
  1008.         return;
  1009.     }
  1010.         
  1011.     progressDialog = GetNewDialog(1005, nil, (WindowPtr)-1);
  1012.         
  1013.     DrawDialog(progressDialog);
  1014.         
  1015.     printerPort = PrOpenDoc(theDoc->thePrintSetup, nil, nil);
  1016.     SetPort((GrafPtr)printerPort);
  1017.         
  1018.     // Create a temporary window(which is not shown)
  1019.     
  1020.     tempWind = NewWindow( nil, &tempWindRect, "\p",
  1021.                                 false, documentProc, (WindowPtr)-1, false, 0);
  1022.     
  1023.     // Duplicate the text edit rec
  1024.     printView = (*(theDoc->thePrintSetup))->prInfo.rPage;
  1025.     DuplicateStyleTERec ( theDoc->theText, &printerTE, &printView, (GrafPtr)tempWind );
  1026.     
  1027.     // Work out the offsets
  1028.     
  1029.     (*printerTE)->destRect = printView; // GetPageEnds calls TECalText
  1030.         
  1031.     GetPageEnds(printView.bottom-printView.top,
  1032.                             printerTE,
  1033.                             pageBounds,
  1034.                             &nPages);
  1035.         
  1036.     TEDeactivate(printerTE);
  1037.     
  1038.     // Set the TERec to the printer port
  1039.     (*printerTE)->inPort = (GrafPtr)printerPort;
  1040.     
  1041.     for (pageCtr = 0; pageCtr <= nPages-1; pageCtr++)
  1042.         if (!abort)
  1043.         {
  1044.             PrOpenPage(printerPort, nil);
  1045.                                         
  1046.             rectToClip = printView;
  1047.             
  1048.             if (pageCtr > 0)
  1049.                 rectToClip.bottom = rectToClip.top + (pageBounds[pageCtr]-pageBounds[pageCtr-1]);
  1050.             else
  1051.                 rectToClip.bottom = rectToClip.top + pageBounds[pageCtr];
  1052.                 
  1053.             ClipRect(&rectToClip);
  1054.             
  1055.             if (PrError() == iPrAbort)
  1056.                 abort = true;
  1057.                 
  1058.             if (! abort)
  1059.                 TEUpdate(&printView, printerTE);
  1060.                                     
  1061.             if (PrError() == iPrAbort)
  1062.                 abort = true;
  1063.                 
  1064.             PrClosePage(printerPort);
  1065.             
  1066.             TEScroll(0,rectToClip.top-rectToClip.bottom, printerTE);
  1067.         }
  1068.     
  1069.     TEDispose(printerTE);
  1070.     DisposeWindow ( tempWind );
  1071.     PrCloseDoc(printerPort);
  1072.     
  1073.     if (( (*(theDoc->thePrintSetup))->prJob.bJDocLoop == bSpoolLoop ) && 
  1074.             ( PrError() == noErr ) && (! abort))
  1075.         PrPicFile( theDoc->thePrintSetup, nil, nil, nil, &thePrinterStatus);
  1076.     
  1077.     PrClose();
  1078.     
  1079.     DisposDialog(progressDialog);
  1080.     
  1081.     SetPort(oldPort);
  1082.     InvalRect(&oldPort->portRect);
  1083. }